//! CTA传感器模块
//! 
//! 提供商品交易顾问(CTA)相关的传感器功能

use std::collections::HashMap;
use serde::{Deserialize, Serialize};
use chrono::{DateTime, Utc};
use crate::objects::bar::RawBar;
use super::event::{Event, EventType, EventLevel, EventHandler};

/// CTA传感器
pub struct CtaSensor {
    /// 传感器配置
    config: HashMap<String, serde_json::Value>,
    /// 检测阈值
    thresholds: HashMap<String, f64>,
    /// 是否启用
    enabled: bool,
}

impl CtaSensor {
    /// 创建新的CTA传感器
    pub fn new(config: HashMap<String, serde_json::Value>) -> Self {
        let mut thresholds = HashMap::new();
        thresholds.insert("price_break".to_string(), 0.05);
        thresholds.insert("volume_spike".to_string(), 2.0);
        thresholds.insert("momentum_change".to_string(), 0.1);
        
        Self {
            config,
            thresholds,
            enabled: true,
        }
    }
    
    /// 设置阈值
    pub fn set_threshold(&mut self, name: &str, value: f64) {
        self.thresholds.insert(name.to_string(), value);
    }
    
    /// 启用或禁用传感器
    pub fn set_enabled(&mut self, enabled: bool) {
        self.enabled = enabled;
    }
    
    /// 检测CTA相关事件
    pub fn detect_events(&self, bars: &[RawBar]) -> Vec<Event> {
        if !self.enabled || bars.is_empty() {
            return vec![];
        }
        
        let mut events = Vec::new();
        
        // 检测价格突破
        if let Some(event) = self.detect_price_break(bars) {
            events.push(event);
        }
        
        // 检测成交量异常
        if let Some(event) = self.detect_volume_spike(bars) {
            events.push(event);
        }
        
        // 检测动量变化
        if let Some(event) = self.detect_momentum_change(bars) {
            events.push(event);
        }
        
        events
    }
    
    /// 检测价格突破
    fn detect_price_break(&self, bars: &[RawBar]) -> Option<Event> {
        let threshold = self.thresholds.get("price_break").unwrap_or(&0.05);
        
        if bars.len() < 20 {
            return None;
        }
        
        let current_bar = &bars[bars.len() - 1];
        let previous_bars = &bars[bars.len() - 20..bars.len() - 1];
        
        let avg_price: f64 = previous_bars.iter().map(|b| b.close).sum::<f64>() / previous_bars.len() as f64;
        let price_change = (current_bar.close - avg_price) / avg_price;
        
        if price_change.abs() > *threshold {
            let level = if price_change.abs() > *threshold * 2.0 {
                EventLevel::Critical
            } else if price_change.abs() > *threshold * 1.5 {
                EventLevel::High
            } else {
                EventLevel::Medium
            };
            
            let description = format!(
                "CTA价格突破: 变化率 {:.2}%",
                price_change * 100.0
            );
            
            let mut event = Event::new(
                format!("cta_price_break_{}", current_bar.dt.timestamp()),
                EventType::PriceBreak,
                level,
                current_bar.dt,
                description,
                current_bar.symbol.clone(),
            );
            
            event.add_data("price_change".to_string(), serde_json::Value::Number(serde_json::Number::from_f64(price_change).unwrap()));
            event.add_data("threshold".to_string(), serde_json::Value::Number(serde_json::Number::from_f64(*threshold).unwrap()));
            
            Some(event)
        } else {
            None
        }
    }
    
    /// 检测成交量异常
    fn detect_volume_spike(&self, bars: &[RawBar]) -> Option<Event> {
        let threshold = self.thresholds.get("volume_spike").unwrap_or(&2.0);
        
        if bars.len() < 20 {
            return None;
        }
        
        let current_bar = &bars[bars.len() - 1];
        let previous_bars = &bars[bars.len() - 20..bars.len() - 1];
        
        let avg_volume: f64 = previous_bars.iter().map(|b| b.vol).sum::<f64>() / previous_bars.len() as f64;
        let volume_ratio = current_bar.vol / avg_volume;
        
        if volume_ratio > *threshold {
            let level = if volume_ratio > *threshold * 3.0 {
                EventLevel::Critical
            } else if volume_ratio > *threshold * 2.0 {
                EventLevel::High
            } else {
                EventLevel::Medium
            };
            
            let description = format!(
                "CTA成交量异常: 成交量比率 {:.2}",
                volume_ratio
            );
            
            let mut event = Event::new(
                format!("cta_volume_spike_{}", current_bar.dt.timestamp()),
                EventType::VolumeAnomaly,
                level,
                current_bar.dt,
                description,
                current_bar.symbol.clone(),
            );
            
            event.add_data("volume_ratio".to_string(), serde_json::Value::Number(serde_json::Number::from_f64(volume_ratio).unwrap()));
            event.add_data("threshold".to_string(), serde_json::Value::Number(serde_json::Number::from_f64(*threshold).unwrap()));
            
            Some(event)
        } else {
            None
        }
    }
    
    /// 检测动量变化
    fn detect_momentum_change(&self, bars: &[RawBar]) -> Option<Event> {
        let threshold = self.thresholds.get("momentum_change").unwrap_or(&0.1);
        
        if bars.len() < 10 {
            return None;
        }
        
        let current_bar = &bars[bars.len() - 1];
        let previous_bars = &bars[bars.len() - 10..bars.len() - 1];
        
        // 计算动量（价格变化率）
        let momentum: f64 = previous_bars.windows(2)
            .map(|w| (w[1].close - w[0].close) / w[0].close)
            .sum::<f64>() / (previous_bars.len() - 1) as f64;
        
        let current_momentum = (current_bar.close - previous_bars.last().unwrap().close) / previous_bars.last().unwrap().close;
        let momentum_change = (current_momentum - momentum).abs();
        
        if momentum_change > *threshold {
            let level = if momentum_change > *threshold * 2.0 {
                EventLevel::Critical
            } else if momentum_change > *threshold * 1.5 {
                EventLevel::High
            } else {
                EventLevel::Medium
            };
            
            let description = format!(
                "CTA动量变化: 变化率 {:.2}%",
                momentum_change * 100.0
            );
            
            let mut event = Event::new(
                format!("cta_momentum_change_{}", current_bar.dt.timestamp()),
                EventType::TechnicalSignal,
                level,
                current_bar.dt,
                description,
                current_bar.symbol.clone(),
            );
            
            event.add_data("momentum_change".to_string(), serde_json::Value::Number(serde_json::Number::from_f64(momentum_change).unwrap()));
            event.add_data("threshold".to_string(), serde_json::Value::Number(serde_json::Number::from_f64(*threshold).unwrap()));
            
            Some(event)
        } else {
            None
        }
    }
}

impl EventHandler for CtaSensor {
    fn handle_event(&mut self, event: &Event) -> Result<(), String> {
        // CTA事件处理逻辑
        println!("CTA传感器处理事件: {}", event.get_summary());
        Ok(())
    }
    
    fn supports_event_type(&self, event_type: EventType) -> bool {
        matches!(event_type, EventType::PriceBreak | EventType::VolumeAnomaly | EventType::TechnicalSignal)
    }
    
    fn get_name(&self) -> &str {
        "CtaSensor"
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    
    #[test]
    fn test_cta_sensor_creation() {
        let config = HashMap::new();
        let sensor = CtaSensor::new(config);
        
        assert!(sensor.enabled);
        assert_eq!(sensor.thresholds.len(), 3);
    }
    
    #[test]
    fn test_cta_sensor_detection() {
        let config = HashMap::new();
        let sensor = CtaSensor::new(config);
        
        // 创建测试K线数据
        let mut bars = Vec::new();
        for i in 0..25 {
            let bar = RawBar {
                symbol: "000001.SZ".to_string(),
                dt: Utc::now() + chrono::Duration::days(i),
                open: 10.0,
                close: if i < 20 { 10.0 } else { 11.0 }, // 最后5根K线价格上涨
                high: 11.0,
                low: 9.0,
                vol: if i < 20 { 1000.0 } else { 3000.0 }, // 最后5根K线成交量放大
                amount: 10000.0,
                cache: None,
            };
            bars.push(bar);
        }
        
        let events = sensor.detect_events(&bars);
        assert!(!events.is_empty());
        
        // 检查是否有价格突破事件
        let price_break_events: Vec<_> = events.iter()
            .filter(|e| e.event_type == EventType::PriceBreak)
            .collect();
        assert!(!price_break_events.is_empty());
        
        // 检查是否有成交量异常事件
        let volume_events: Vec<_> = events.iter()
            .filter(|e| e.event_type == EventType::VolumeAnomaly)
            .collect();
        assert!(!volume_events.is_empty());
    }
    
    #[test]
    fn test_cta_sensor_threshold() {
        let mut config = HashMap::new();
        let mut sensor = CtaSensor::new(config);
        
        sensor.set_threshold("price_break", 0.1);
        assert_eq!(sensor.thresholds.get("price_break"), Some(&0.1));
        
        sensor.set_enabled(false);
        assert!(!sensor.enabled);
    }
} 